<template>
  <div class="enhanced-file-selector">
    <!-- 文件选择按钮组 -->
    <div class="selector-buttons">
      <el-button-group>
        <el-button 
          type="primary" 
          @click="selectFiles"
          :loading="selecting"
          :icon="Files"
        >
          选择文件
        </el-button>
        <el-button 
          type="primary" 
          @click="selectFolder"
          :loading="selecting"
          :icon="Folder"
          v-if="allowFolder"
        >
          选择文件夹
        </el-button>
      </el-button-group>
      
      <!-- 快速选择按钮 -->
      <div class="quick-select" v-if="showQuickSelect">
        <el-button 
          v-for="preset in filePresets" 
          :key="preset.name"
          size="small"
          @click="selectFilesByType(preset)"
          :icon="preset.icon"
        >
          {{ preset.name }}
        </el-button>
      </div>
    </div>

    <!-- 选中文件列表 -->
    <div v-if="selectedFiles.length > 0" class="selected-files">
      <div class="files-header">
        <span class="files-count">已选择 {{ selectedFiles.length }} 个文件</span>
        <el-button size="small" text @click="clearSelection">
          <el-icon><Close /></el-icon>
          清空
        </el-button>
      </div>
      
      <div class="files-list">
        <div 
          v-for="(file, index) in selectedFiles" 
          :key="index"
          class="file-item"
        >
          <el-icon class="file-icon">
            <component :is="getFileIcon(file)" />
          </el-icon>
          <div class="file-info">
            <div class="file-name" :title="file.name">{{ file.name }}</div>
            <div class="file-details">
              <span class="file-size">{{ formatFileSize(file.size) }}</span>
              <span class="file-type">{{ getFileType(file) }}</span>
            </div>
          </div>
          <el-button 
            size="small" 
            text 
            @click="removeFile(index)"
            class="remove-btn"
          >
            <el-icon><Close /></el-icon>
          </el-button>
        </div>
      </div>
    </div>

    <!-- 文件预览 -->
    <div v-if="showPreview && previewFile" class="file-preview">
      <div class="preview-header">
        <span>文件预览</span>
        <el-button size="small" text @click="closePreview">
          <el-icon><Close /></el-icon>
        </el-button>
      </div>
      <div class="preview-content">
        <!-- 图片预览 -->
        <img 
          v-if="isImage(previewFile)" 
          :src="previewFile.url" 
          :alt="previewFile.name"
          class="preview-image"
        />
        <!-- 文本预览 -->
        <pre 
          v-else-if="isText(previewFile)" 
          class="preview-text"
        >{{ previewFile.content }}</pre>
        <!-- 其他文件类型 -->
        <div v-else class="preview-placeholder">
          <el-icon class="placeholder-icon">
            <Document />
          </el-icon>
          <p>{{ previewFile.name }}</p>
          <p class="file-info">{{ formatFileSize(previewFile.size) }}</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { ElMessage } from 'element-plus'
import { 
  Files, Folder, Close, Document, Picture, VideoPlay, 
  Headset, Reading, DataAnalysis 
} from '@element-plus/icons-vue'

// Props
interface Props {
  multiple?: boolean
  allowFolder?: boolean
  acceptTypes?: string[]
  maxFileSize?: number // MB
  showQuickSelect?: boolean
  showPreview?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  multiple: true,
  allowFolder: true,
  acceptTypes: () => [],
  maxFileSize: 100,
  showQuickSelect: true,
  showPreview: false
})

// Emits
const emit = defineEmits<{
  filesSelected: [files: File[]]
  folderSelected: [path: string]
}>()

// 状态管理
const selecting = ref(false)
const selectedFiles = ref<File[]>([])
const previewFile = ref<any>(null)

// 检测是否为Electron环境
const isElectron = !!(window as any).electronAPI

// 文件类型预设
const filePresets = [
  {
    name: '图片',
    icon: Picture,
    extensions: ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'],
    mimeTypes: ['image/*']
  },
  {
    name: '文档',
    icon: Reading,
    extensions: ['.pdf', '.doc', '.docx', '.txt', '.md'],
    mimeTypes: ['application/pdf', 'application/msword', 'text/*']
  },
  {
    name: '视频',
    icon: VideoPlay,
    extensions: ['.mp4', '.avi', '.mov', '.wmv', '.flv'],
    mimeTypes: ['video/*']
  },
  {
    name: '音频',
    icon: Headset,
    extensions: ['.mp3', '.wav', '.flac', '.aac'],
    mimeTypes: ['audio/*']
  },
  {
    name: '表格',
    icon: DataAnalysis,
    extensions: ['.xlsx', '.xls', '.csv'],
    mimeTypes: ['application/vnd.ms-excel', 'text/csv']
  }
]

// 格式化文件大小
const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 获取文件类型
const getFileType = (file: File): string => {
  const extension = file.name.split('.').pop()?.toUpperCase()
  return extension || 'Unknown'
}

// 获取文件图标
const getFileIcon = (file: File) => {
  const type = file.type.toLowerCase()
  const name = file.name.toLowerCase()
  
  if (type.startsWith('image/')) return Picture
  if (type.startsWith('video/')) return VideoPlay
  if (type.startsWith('audio/')) return Headset
  if (type.includes('pdf') || name.endsWith('.pdf')) return Reading
  if (type.includes('excel') || name.endsWith('.xlsx') || name.endsWith('.xls')) return DataAnalysis
  
  return Document
}

// 判断是否为图片
const isImage = (file: any): boolean => {
  return file.type?.startsWith('image/')
}

// 判断是否为文本
const isText = (file: any): boolean => {
  return file.type?.startsWith('text/') || file.name?.endsWith('.txt')
}

// 选择文件
const selectFiles = async () => {
  selecting.value = true
  
  try {
    let files: File[] = []
    
    if (isElectron) {
      // 使用Electron原生文件对话框
      const electronAPI = (window as any).electronAPI
      const filePaths = await electronAPI.file.select({
        multiple: props.multiple,
        filters: getElectronFilters()
      })
      
      // 将文件路径转换为File对象（这里需要实际的文件读取逻辑）
      files = await convertPathsToFiles(filePaths)
    } else {
      // 使用Web文件选择
      files = await selectFilesWeb()
    }
    
    if (files.length > 0) {
      addFiles(files)
    }
  } catch (error) {
    console.error('文件选择失败:', error)
    ElMessage.error('文件选择失败')
  } finally {
    selecting.value = false
  }
}

// 选择文件夹
const selectFolder = async () => {
  if (!isElectron) {
    ElMessage.warning('文件夹选择功能仅在桌面版中可用')
    return
  }
  
  selecting.value = true
  
  try {
    const electronAPI = (window as any).electronAPI
    const folderPath = await electronAPI.file.selectFolder()
    
    if (folderPath) {
      emit('folderSelected', folderPath)
      ElMessage.success(`已选择文件夹: ${folderPath}`)
    }
  } catch (error) {
    console.error('文件夹选择失败:', error)
    ElMessage.error('文件夹选择失败')
  } finally {
    selecting.value = false
  }
}

// 按类型选择文件
const selectFilesByType = async (preset: any) => {
  selecting.value = true
  
  try {
    let files: File[] = []
    
    if (isElectron) {
      const electronAPI = (window as any).electronAPI
      const filePaths = await electronAPI.file.select({
        multiple: props.multiple,
        filters: [
          {
            name: preset.name,
            extensions: preset.extensions.map((ext: string) => ext.slice(1)) // 移除点号
          }
        ]
      })
      
      files = await convertPathsToFiles(filePaths)
    } else {
      files = await selectFilesWeb(preset.mimeTypes.join(','))
    }
    
    if (files.length > 0) {
      addFiles(files)
    }
  } catch (error) {
    console.error('文件选择失败:', error)
    ElMessage.error('文件选择失败')
  } finally {
    selecting.value = false
  }
}

// Web环境文件选择
const selectFilesWeb = (accept?: string): Promise<File[]> => {
  return new Promise((resolve) => {
    const input = document.createElement('input')
    input.type = 'file'
    input.multiple = props.multiple
    if (accept) input.accept = accept
    
    input.onchange = (e) => {
      const files = Array.from((e.target as HTMLInputElement).files || [])
      resolve(files)
    }
    
    input.click()
  })
}

// 获取Electron文件过滤器
const getElectronFilters = () => {
  if (props.acceptTypes.length === 0) {
    return [{ name: 'All Files', extensions: ['*'] }]
  }
  
  return [
    {
      name: 'Allowed Files',
      extensions: props.acceptTypes.map(type => type.startsWith('.') ? type.slice(1) : type)
    },
    { name: 'All Files', extensions: ['*'] }
  ]
}

// 将文件路径转换为File对象（模拟实现）
const convertPathsToFiles = async (paths: string[]): Promise<File[]> => {
  // 这里应该实现实际的文件读取逻辑
  // 目前返回模拟的File对象
  return paths.map(path => {
    const name = path.split(/[/\\]/).pop() || 'unknown'
    return new File([''], name, { type: 'application/octet-stream' })
  })
}

// 添加文件
const addFiles = (files: File[]) => {
  const validFiles = files.filter(file => {
    // 验证文件大小
    if (file.size > props.maxFileSize * 1024 * 1024) {
      ElMessage.warning(`文件 ${file.name} 超过大小限制`)
      return false
    }
    
    // 验证文件类型
    if (props.acceptTypes.length > 0) {
      const extension = '.' + file.name.split('.').pop()?.toLowerCase()
      const mimeType = file.type.toLowerCase()
      
      const isValid = props.acceptTypes.some(type => {
        if (type.startsWith('.')) {
          return extension === type.toLowerCase()
        }
        return mimeType.includes(type.toLowerCase())
      })
      
      if (!isValid) {
        ElMessage.warning(`文件 ${file.name} 类型不支持`)
        return false
      }
    }
    
    return true
  })
  
  if (props.multiple) {
    selectedFiles.value.push(...validFiles)
  } else {
    selectedFiles.value = validFiles.slice(0, 1)
  }
  
  emit('filesSelected', selectedFiles.value)
}

// 移除文件
const removeFile = (index: number) => {
  selectedFiles.value.splice(index, 1)
  emit('filesSelected', selectedFiles.value)
}

// 清空选择
const clearSelection = () => {
  selectedFiles.value = []
  emit('filesSelected', [])
}

// 关闭预览
const closePreview = () => {
  previewFile.value = null
}
</script>

<style scoped>
.enhanced-file-selector {
  width: 100%;
}

.selector-buttons {
  margin-bottom: 16px;
}

.quick-select {
  margin-top: 12px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.selected-files {
  border: 1px solid #EBEEF5;
  border-radius: 8px;
  padding: 16px;
  margin-bottom: 16px;
}

.files-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid #EBEEF5;
}

.files-count {
  font-weight: 500;
  color: #303133;
}

.files-list {
  max-height: 300px;
  overflow-y: auto;
}

.file-item {
  display: flex;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid #F5F7FA;
}

.file-item:last-child {
  border-bottom: none;
}

.file-icon {
  font-size: 20px;
  color: #409EFF;
  margin-right: 12px;
}

.file-info {
  flex: 1;
  min-width: 0;
}

.file-name {
  font-weight: 500;
  color: #303133;
  margin-bottom: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-details {
  display: flex;
  gap: 12px;
  font-size: 12px;
  color: #909399;
}

.remove-btn {
  margin-left: 8px;
}

.file-preview {
  border: 1px solid #EBEEF5;
  border-radius: 8px;
  overflow: hidden;
}

.preview-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: #F5F7FA;
  border-bottom: 1px solid #EBEEF5;
  font-weight: 500;
}

.preview-content {
  padding: 16px;
  max-height: 400px;
  overflow: auto;
}

.preview-image {
  max-width: 100%;
  max-height: 300px;
  object-fit: contain;
}

.preview-text {
  font-family: 'Courier New', monospace;
  font-size: 12px;
  line-height: 1.5;
  color: #303133;
  background: #F5F7FA;
  padding: 12px;
  border-radius: 4px;
  overflow-x: auto;
}

.preview-placeholder {
  text-align: center;
  padding: 40px;
}

.placeholder-icon {
  font-size: 48px;
  color: #C0C4CC;
  margin-bottom: 16px;
}

.preview-placeholder p {
  margin: 8px 0;
  color: #606266;
}

.preview-placeholder .file-info {
  color: #909399;
  font-size: 14px;
}
</style>
